#include "word.h"
#include "gui.h"

static const uint8_t utf8_length_table[256] = {
	//192个1，32个2，16个3，8个4，4个5，2个6
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
	4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1
};

uint16_t word::get_utf8(const char *word, uint32_t &utf8)
{
	char *word_ = (char *)word;
	uint32_t utf8_ = utf8_length_table[(uint8_t)*word_]; //根据第1个字节的值，再从表中得到字节长度
	switch (utf8_)
	{
	case 1:
		utf8 = *word_;
		break;
	case 2:
		utf8 = (*word_ << 8) | (*(word_ + 1)); //把2个字节合成16位。
		break;
	case 3:
		utf8 = (*word_ << 16) | ((*(word_ + 1)) << 8) | *(word_ + 2);
		break;
	case 4:
		utf8 = (*word_ << 24) | ((*(word_ + 1)) << 16) | (*(word_ + 2) << 8) | *(word_ + 3);
		break;
	default:
		break;
	}
	return utf8_;
}

void word::draw_string(window *win, const char *string, uint16_t x, uint16_t y, uint32_t color, font_information const *font)
{
	uint32_t utf8;
	while (*string)
	{
		string += get_utf8(string, utf8);					 //返回字的字节长度
		x += draw_single_char(win, utf8, x, y, font, color); //返回字的宽度
	}
}

uint16_t word::draw_single_char(window *win, uint32_t utf8, uint16_t x, uint16_t y, const font_information *font, uint32_t color)
{
	if (font)
	{
		const lattice *lattice_ = get_lattice(font, utf8);
		if (lattice_)
		{
			draw_lattice(win, x, y, lattice_->width_, font->height_, lattice_->data_, color);
			return lattice_->width_;
		}
	}
	//lattice/Font not found, draw "X"
	uint16_t Len = 16;
	for (uint16_t Y2 = 0; Y2 < Len; Y2++)
	{
		for (uint16_t X2 = 0; X2 < Len; X2++)
		{
			uint16_t Diff = X2 - Y2;
			uint16_t Sum = X2 + Y2;
			(Diff == 0 || Diff == -1 || Diff == 1 || Sum == Len || Sum == (Len - 1) || Sum == (Len + 1)) ? win->draw_pixel(x + X2, y + Y2, color) : win->draw_pixel(x + X2, y + Y2, 0);
		}
	}
	return Len;
}

void word::draw_lattice(window *win, uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint8_t *data, uint32_t color)
{
	uint8_t block = *data++;
	uint8_t num = *data++;
	for (uint16_t Y = 0; Y < height; Y++)
	{
		for (uint16_t X = 0; X < width; X++)
		{
			if (block)
			{
				win->draw_pixel(x + X, y + Y, color);
			}
			if (--num == 0)
			{ 
				block = *data++; //reload new block
				num = *data++;
			}
		}
	}
}

lattice *word::get_lattice(const font_information *font, uint32_t utf8)
{
	int16_t First = 0, Last = font->num_ - 1, Middle = (First + Last) / 2;
	while (First <= Last)
	{
		if (font->lattice_[Middle].utf8_ < utf8)
		{
			First = Middle + 1;
		}
		else if (font->lattice_[Middle].utf8_ == utf8)
		{
			return &font->lattice_[Middle];
		}
		else
		{
			Last = Middle - 1;
		}
		Middle = (First + Last) / 2;
	}
	return nullptr;
}